home *** CD-ROM | disk | FTP | other *** search
- /*
- CPRINT, Print a (fairly) neat listing of a c program
-
- Programmed by Andrew L. Bender, M. D.
- June 24, 1984 - Version 1.0
- June 26, 1984 - Version 1.1
- Fix some bugs in string processing
- July 3, 1984 - Version 1.2
- Allow for printer file device.
- Count source statements
-
- Permission is hereby given to freely distribute this
- program but it may not be sold. This program may be
- modified by anyone as long as this notice remains.
- The purpose of this program was to test the CI86
- optimizing c compiler. It does a clean compilation
- of this program which tests most features of the
- c language as described by Kernighan and Ritchie in
- their book "The C Programming Language."
- CI-86 is a trademark of Computer Innovations,
- Tinton Falls NJ for their implementation of the full
- c programming language as described in Kernighan and
- Ritchie.
-
- The listing contains two columns on the left:
- column 1 is the "nesting level" of compound
- statements and column 2 is a rough idea of
- what the line number will be. It is actually
- a count of "\n" characters. The heading on
- each page gives the name of the file being
- printed and the date and time it was created.
-
- If braces, brackets or parenthesis are unbalanced
- this will be reported at the end of the listing.
- A complete syntactical analysis of the program
- would require more effort but would be worth it as
- an exercise of much value in learning the c language
- because of the facility and fluency needed to write
- such a checker.
- A program checker "lint" is quite through in its
- analysis of c programs and is available on most
- UNIX systems.
- */
- #include "local.h"
- #define LPP 58
- #define TAB 3
- #define CHPL 74
- /* LPP=lines per page
- TAB = number of spaces to indent for a tab
- CHPL = characters to print on each line (74 is very tight)
- because the line and level count take up 8 columns
- */
- unsigned int hour,minute,second,month,day,year;
- int pagect, level, tabct, lines, stmnt, linect;
- typedef int void;
- typedef int boolean;
- struct regval { int ax, bx, cx, dx, si, di, ds, es; };
- struct regval callreg, retreg;
- unsigned char title[60];
- boolean comment, quote, squote, instrng;
- unsigned char lineimage[520];
- unsigned char fmt[]=
- {"\fListing of file: %s Catalogued on %d/%d/%d At %d:%02d:%02d\
- Page %d \n\n"};
- unsigned char output[60]={"PRN:"};
-
- /* top of page routine */
-
- void toppage(pr)
- FILE *pr;
- {
- fprintf(pr,fmt,title,month,day,year,hour,minute,second,pagect);
- linect=1;
- pagect++;
- }
-
- /* main program */
-
- main(argc,argv)
- int argc;
- unsigned char *argv[];
- {
- int i,j,kk,jj,n;
- unsigned char buf[600], fname [254];
- unsigned char k;
- int *pb;
- int lbrace, rbrace, lparen, rparen, lbrack, rbrack;
- extern FILE *fopen();
- extern FILE *fclose();
- extern char *fgets();
- FILE *prn, *fd;
- fprintf(stderr,"C Program Listing Version 1.2\n");
- if (argc<2)
- {
- fprintf(stderr,"Type In Filename To Print: ");
- gets(buf,254,stdin); /*get user file name if not on control card*/
- pb=index(buf,'\n');
- *pb='\0';
- }
- else strcpy(buf,argv[1]); /*copy control stmnt string to user bfr*/
- makefnam(buf,".c",fname); /*convert file name to filename.c*/
- fprintf(stderr,"Listing Of File: %s \n",fname);
- if (argc==3) strcpy(output,argv[2]); /*copy prt file name to output*/
- prn=fopen(output,"w"); /*open printer*/
- if(prn==NULL) {
- fprintf(stderr,"Assignment of print device: %s failed.",output);
- exit(1);
- }
- fd=fopen(fname,"r"); /*open program file to list*/
- if (fd==NULL) {
- fprintf(stderr,"Cannot Open File: %s \n",fname);
- exit(1); /*error exit*/
- }
- linect = pagect = 1; /*set page & line count to one*/
- stmnt = j = rbrack = lbrack = rbrace = lbrace = rparen = lparen = 0;
- callreg.bx =*fd; /*get file handle*/
- callreg.ax = 0x5700 ; /*get file data */
- sysint21(&callreg,&retreg); /*fetch file date and time*/
-
- /* n.b. -> ci86 c documentation is a bit confusing here.
- the structure is naturally a memory area so it conflicts
- in that sense with the register lo-hi multiplexing */
-
- month=(retreg.dx & 0x01E0)>>5;
- day=retreg.dx & 0x001F;
- year=((retreg.dx >>9)& 0x00EF)+80;
- hour=(retreg.cx >>11) & 0x001F;
- minute=(retreg.cx & 0x07E0)>>5;
- second=(retreg.cx & 0x001F)<<1; /* multiply by 2 */
- strcpy(title,fname);
- comment=squote=instrng=quote=FALSE;
- toppage(prn); /*take top of page action*/
- while(fgets(lineimage,519,fd)!=NULL){
- jj=strlen(lineimage);
- for(i=0;k=lineimage[i],k!='\0'&& i<jj;i++){
- kk=k;
- if (kk=='\n')
- {
- lines++;
- }
- if (comment==FALSE && instrng==FALSE) {
- /* switch is entered when processing outside a comment
- or string. If in a comment or string (either " or ') then
- the if statement drops thru to the else at the
- conclusion of the loop to turn processing back on
- In the case of alphanumerics the loop is totally ignored.
- */
- if (isalnum(k)==0){ /* don't switch on alphanumerics */
- switch (kk) {
- case '{':
- level++;
- lbrace++;
- break;
- case '}':
- rbrace++;
- level--;
- break;
- case '(':
- lparen++;
- break;
- case ')':
- rparen++;
- break;
- case '[':
- lbrack++;
- break;
- case ']':
- rbrack++;
- break;
- case '/':
- comment= lineimage[i+1]=='*';
- break;
- case ';':
- stmnt++;
- break;
- case '\'':
- quote=!squote;
- instrng=quote|squote;
- break;
- case '"':
- squote= !quote;
- instrng= squote|quote;
- break;
- }
- }
- }
- else { /*if comment or instrng == TRUE*/
- if (comment==TRUE && k=='*' && lineimage[i+1]=='/')
- comment=FALSE;
- if (quote==TRUE && k=='\'' &&
- (lineimage[i-1] != '\\' ||
- (lineimage[i-2]=='\\' && lineimage[i-1]=='\\')))
- quote=FALSE;
- if (squote==TRUE && k=='"') squote=FALSE;
- instrng = quote | squote;
- }
- if (k=='\t') for(n=j;buf[j++]=' ',j<n+TAB;);
- else buf[j++]=k;
- if (j>CHPL || k == '\n'){
- if (k != '\n')
- buf[j++]='\n';
- buf[j]='\0';
- fprintf(prn,"%2d%4d: %s",level,lines,buf);
- j=0;
- if (linect++>LPP) toppage(prn);
- }
- }
- }
- fclose(fd);
- if (level==0 && rbrack==lbrack && rparen==lparen)
- {
- fprintf(prn,"\n%d Statements in source code. \
- Braces, brackets and parenthesis are balanced.\n",stmnt);
- }
- else
- {
- fprintf(prn,"\nUnbalanced pairs { %d, } %d, [ %d, ] %d, ( %d, ) %d\n",
- lbrace,rbrace,lbrack,rbrack,lparen,rparen);
- fclose(prn);
- }
- }